﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Channels;


namespace ERPService
{
    public class Token
    {
        /// <summary>
        /// 千分之一秒/每天
        /// </summary>
        public static int MilliSecOfDays = (60 * 60 * 24 * 1000);
        /// <summary>
        /// 取新的token
        /// </summary>
        /// <returns>Token(int)</returns>
        public static int Next() { return (int)DateTime.Now.TimeOfDay.TotalMilliseconds; }
        /// <summary>
        /// 算出新舊token經歷的時間(千分之一秒)
        /// </summary>
        /// <param name="old">舊Token</param>
        /// <param name="now">新Token</param>
        /// <returns></returns>
        public static int Interval(int old, int now)
        {
            return now > old ? (now - old) : (now + MilliSecOfDays) - old;

        }
    }

    public class UserIdentify
    {
        private workEntities db= null;
        private User user = null;
        private string _Account;
        private int _token;
        private Command _cmd;


        public UserIdentify(string Account, int token)
        {
            _Account = Account;
            _token = token;
            _cmd = new Command();
        }

        public workEntities DB
        {
            get { return db; }
        }

        public User USER
        {
            get { return user; }
        }


        /// <summary>
        /// 驗證玩家身分(第一次登入)
        /// </summary>
        /// <param name="Password"></param>
        /// <returns></returns>
        public int BeginCheck(string Password, string MAC)
        {
            try
            {
                db = new workEntities();
                user = (from g in db.Users
                        where g.Name == _Account && g.Password == Password
                        select g).FirstOrDefault();
            }
            catch
            {
                //資料庫異常
                _cmd.Error = -4;
                return -4;
            }

            if (user == null)
            {
                //資料不存在
                _cmd.Error = -1;
                return -1;
            }

            if (user.MAC != MAC)
            {
                _cmd.Error = -2;
                return -2;
            }

            return 0;       
        }

        /// <summary>
        /// 驗證玩家身分
        /// </summary>
        /// <param name="verifyToken">是否檢驗Token</param>
        /// <returns></returns>
        public int BeginCheck(bool verifyToken = true)
        {
            try
            {
                db = new workEntities();
                user = (from g in db.Users
                     where g.Name == _Account
                     select g).FirstOrDefault();
            }
            catch
            {
                //資料庫異常
                _cmd.Error = -4;
                return -4;
            }

            if (user == null)
            {
                //資料不存在
                _cmd.Error = -4;
                return -4;
            }

            if (!verifyToken) return 0;

            if (user.Token != _token)
            {
                if (user.TokenOld == _token)
                {
                    //上個封包遺失
                    //是否重送前一筆資料
                    _cmd.Error = -3;
                    return -3;
                }
                else
                {
                    //超過1小時
                    if (Token.Interval(user.TokenOld, _token) > (60 * 60 * 1000))
                    {
                        //重置
                        _cmd.Error = -2;
                        return -2;
                    }
                    //再重送(這次命令不處理, 補送前兩次封包)
                    _cmd.Error = -5;
                    return -5;
                }
            }
            return 0;
        }

        public Command EndCheck(Object send, int detial)
        {
            if (_cmd.Error == 0)
            {
                user.TokenOld = user.Token;
                user.Token = Token.Next();
                user.LastLogin = DateTime.Now;
                user.IP = getIp();
                db.SaveChanges();
                _cmd.Token = user.Token;
                _cmd.Content = JsonConvert.SerializeObject(send);
            }
            _cmd.Detail = detial;
            return _cmd;
        }

        //取得IP
        public static string getIp()
        {
            OperationContext context = OperationContext.Current;
            using (MessageProperties messageProperties = context.IncomingMessageProperties)
            {
                RemoteEndpointMessageProperty endpointProperty = messageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
                return endpointProperty.Address;
            }
        }
    }
}